package com.imooc.controller;

import com.imooc.constant.IndexConstant;
import com.imooc.enums.YesOrNo;
import com.imooc.pojo.Carousel;
import com.imooc.pojo.Category;
import com.imooc.service.CarouselService;
import com.imooc.service.CategoryService;
import com.imooc.utils.IMOOCJSONResult;
import com.imooc.utils.JsonUtils;
import com.imooc.utils.RedisOperator;
import com.imooc.vo.CategoryVo;
import com.imooc.vo.NewsItemVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @author gcq
 * @Create 2022-01-08
 */
@Api(value = "首页", tags = {"首页展示相关接口"})
@RestController
@RequestMapping("/index")
public class IndexController {

    @Autowired
    CarouselService carouselService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    RedisOperator redisOperator;


    @ApiOperation(value = "获取首页轮播图列表", notes = "获取首页轮播图列表", httpMethod = "GET")
    @GetMapping("/carousel")
    public IMOOCJSONResult carousel()
    {
        String carouselStr = redisOperator.get(IndexConstant.carousel);
        List<Carousel> carouselList = new ArrayList<>();
        if(StringUtils.isEmpty(carouselStr)) {
            carouselList = carouselService.queryAll(YesOrNo.YES.type);
            redisOperator.set(IndexConstant.carousel, JsonUtils.objectToJson(carouselList));
        } else {
            carouselList = JsonUtils.jsonToList(carouselStr, Carousel.class);
        }
        return IMOOCJSONResult.ok(carouselList);

        /**
         * 1、后台运营系统，一旦广告轮播图发生更改，就可以删除缓存，然后重置
         *       也就是在删除或者修改的时候，清空redis中得缓存
         * 2、定时重置，比如每天凌晨三点重置
         *      定时清空
         * 3、每个轮播图都可能是一个广告，每个广告都会有一个过期时间
         */
    }

    /**
     * 首页分类展示需求
     * 1、第一次刷新主页，查询大分类，渲染展示到首页
     * 2、如果移上到大分类，加载其子分类内容，已存在子分类，不进行加载
     *
     * 存进redis中
     *
     */
    @ApiOperation(value = "获取首页一级分类", notes = "获取首页一级分类", httpMethod = "GET")
    @GetMapping("/cats")
    public IMOOCJSONResult  cats()
    {
        String catsStr = redisOperator.get(IndexConstant.cats);
        List<Category> categoryList = new ArrayList<>();
        if(StringUtils.isEmpty(catsStr)){
            categoryList = categoryService.queryAllRootLevelCat();
            redisOperator.set(IndexConstant.cats, JsonUtils.objectToJson(categoryList));
        }
        else {
            categoryList = JsonUtils.jsonToList(catsStr, Category.class);
        }
        return IMOOCJSONResult.ok(categoryList);
    }

    /**
     *
     * 商品分类数据存到redis中
     *
     * @param rootCatId
     * @return
     */
    @ApiOperation(value = "获取商品子分类", notes = "获取商品子分类", httpMethod = "GET")
    @GetMapping("/subCat/{rootCatId}")
    public IMOOCJSONResult subCat(@ApiParam(name = "rootCatId",value = "分类Id", required = true)
                                  @PathVariable Integer rootCatId)
    {
        if(rootCatId == null)
        {
            return IMOOCJSONResult.errorMsg("分类不能为空");
        }

        String subCatStr = redisOperator.get(IndexConstant.catId + rootCatId);
        List<CategoryVo> subCatList = new ArrayList<>();

        if(StringUtils.isEmpty(subCatStr)) {
            subCatList = categoryService.getSubCatList(rootCatId);
            /**
             * 缓存穿透场景
             * 要是数据库没有查询到数据，自然没有放到缓存中，用户大量的请求来访问该接口，就会查询多次数据库，造成数据库压力过大
             * 解决：
             * 数据库中没有查询到数据，也将他放到缓存中，只不过缓存中数据也是空的，避免了缓存击穿
             *
             * 查询的key在redis中不存在
             * 对应的id在数据库中也不存在
             * 此时被非法用户进行攻击，大量的请求会直接打到db上
             * 造成宕机，从而影响到整个系统
             * 这种现象称之为缓存穿透
             * 解决方案：
             * 把空的数据缓存起来，比如空字符串、空对象、空数组和list
             */
            if(subCatList != null && subCatList.size() > 0) {
                redisOperator.set(IndexConstant.catId + rootCatId, JsonUtils.objectToJson(subCatList));
            }
            else {
                redisOperator.set(IndexConstant.catId + rootCatId, JsonUtils.objectToJson(subCatList), 5*60);
            }
        } else {
            subCatList = JsonUtils.jsonToList(subCatStr, CategoryVo.class);
        }

        return IMOOCJSONResult.ok(subCatList);
    }

    @ApiOperation(value = "查询每一个一级分类下的最新6条商品数据", notes = "查询每一个一级分类下的最新6条商品数据", httpMethod = "GET")
    @GetMapping("/sixNewItems/{rootCatId}")
    public IMOOCJSONResult sixNewsItems(@ApiParam(name = "rootCatId",value = "分类Id", required = true)
                                  @PathVariable Integer rootCatId)
    {
        if(rootCatId == null)
        {
            return IMOOCJSONResult.errorMsg("分类不存在");
        }
        List<NewsItemVO> newsItemVOList = categoryService.getSixNewItemsLazy(rootCatId);
        return IMOOCJSONResult.ok(newsItemVOList);
    }
}